#include "../include/tcpConnection.h"
#include "../include/eventLoop.h"
#include <iostream>
#include <sstream>

using std::cout;
using std::ostringstream;

TcpConnection::TcpConnection(int fd,EventLoop * loop)
:_loop(loop)
,_socketIO(fd)
,_socket(fd)
,_localAddr(getLocalAddr())
,_peerAddr(getPeerAddr())
{

}

TcpConnection::~TcpConnection()
{
	
}

void TcpConnection::send(const string & msg)
{
	_socketIO.writen(msg.c_str(),msg.size());
}

void TcpConnection::sendInLoop(const string & msg)
{
	if(_loop)
		_loop->runInLoop(bind(&TcpConnection::send,this,msg));
}

string TcpConnection::receive()
{
	char buff[65535] = {0};
	_socketIO.readLine(buff,sizeof(buff));
	return string(buff);
}

string TcpConnection::toString()
{
	return _localAddr.ip()+ ":" + std::to_string(_localAddr.port()) + " >>>>> " + _peerAddr.ip() + ":" + std::to_string(_peerAddr.port()) + "\n";
}

bool TcpConnection::isClose()
{
	char buff[10] = {0};
	return (recv(_socket.fd(),buff,sizeof(buff),MSG_PEEK) == 0);
}

void TcpConnection::setNewConnectionCallBack(const function<void(const shared_ptr<TcpConnection>&)>& callBack)
{
	_callBackNewConnection = callBack;
}

void TcpConnection::setMessageCallBack(const function<void(const shared_ptr<TcpConnection>&)>& callBack)
{
	_callBackMessage = callBack;
}

void TcpConnection::setCloseCallBack(const function<void(const shared_ptr<TcpConnection>&)>& callBack)
{
	_callBackClose = callBack;
}

void TcpConnection::handleNewConnectionCallBack()
{
	if(_callBackNewConnection)
		_callBackNewConnection(shared_from_this());
	else
		cout << "callBackNewConnection is nullptr\n";
}

void TcpConnection::handleMessageCallBack()
{
	if(_callBackMessage)
		_callBackMessage(shared_from_this());
	else
		cout << "callBackMessage is nullptr\n";
}

void TcpConnection::handleCloseCallBack()
{
	if(_callBackClose)
		_callBackClose(shared_from_this());
	else
		cout << "callBackClose is nullptr\n";
}

InetAddress TcpConnection::getLocalAddr()
{
	struct sockaddr_in addr;
	socklen_t len = sizeof(struct sockaddr); 
	
	int ret = getsockname(_socket.fd(),(struct sockaddr *)&addr,&len);
	if(ret == -1)
		perror("getsockname error");
		
	return InetAddress(addr);
}

InetAddress TcpConnection::getPeerAddr()
{
	struct sockaddr_in addr;
	socklen_t len = sizeof(struct sockaddr); 
	
	int ret = getpeername(_socket.fd(),(struct sockaddr *)&addr,&len);
	if(ret == -1)
		perror("getpeername error");
		
	return InetAddress(addr);
}











